#include "audio_decoder.h"

my_decoder_t my_decoder;

esp_audio_dec_handle_t decoder;

esp_audio_dec_out_frame_t out_frame;
void                      audio_decoder_init(void)
{
    // 解码器配置
    esp_opus_dec_cfg_t opus_cfg = {
        .sample_rate    = 16000,
        .channel        = 1,
        .frame_duration = ESP_OPUS_DEC_FRAME_DURATION_60_MS,
        .self_delimited = false};

    esp_opus_dec_open(&opus_cfg, sizeof(opus_cfg), &decoder);
}

void audio_decoder_task(void *);

void audio_decoder_start(RingbufHandle_t in_buffer)
{

    my_decoder.is_running = true;
    my_decoder.input      = in_buffer;
    xTaskCreatePinnedToCoreWithCaps(audio_decoder_task,
                                    "audio_decoder_task",
                                    64 * 1024,
                                    NULL,
                                    5,
                                    NULL,
                                    0,   // cpu核心
                                    MALLOC_CAP_SPIRAM);
}

void audio_decoder_task(void *args)
{
    // 输入帧
    esp_audio_dec_in_raw_t in_frame;
    memset(&in_frame, 0, sizeof(esp_audio_dec_in_raw_t));
    // 输出帧
    esp_audio_dec_out_frame_t out_frame;
    out_frame.buffer = heap_caps_malloc(8 * 1024, MALLOC_CAP_SPIRAM);
    out_frame.len    = 8 * 1024;
    while(my_decoder.is_running)
    {
        // 从输入环形缓冲区读取数据
        in_frame.buffer  = xRingbufferReceive(my_decoder.input, &in_frame.len, portMAX_DELAY);
        void *raw_buffer = in_frame.buffer;   // 记录缓冲区数据的原始地址, 用于后期归还

        // 一次只能解码一帧, 读到的数据可能包含多帧数据
        while(in_frame.len > 0)
        {
            esp_audio_dec_info_t aud_info;
            esp_opus_dec_decode(decoder, &in_frame, &out_frame, &aud_info);

            in_frame.len -= in_frame.consumed;      // 减掉已经处理的数据, 剩下的是未解码的
            in_frame.buffer += in_frame.consumed;   // 待解码的数据的指针移动

            // 播放音频: 播放解码后的pcm格式化的数据
            bsp_sound_write(out_frame.buffer, out_frame.decoded_size);
        }

        // 归还环形缓冲区
        vRingbufferReturnItem(my_decoder.input, raw_buffer);
    }

    free(out_frame.buffer);
    vTaskDelete(NULL);
}

void audio_decoder_write(char *data, int size)
{
    xRingbufferSend(my_decoder.input, data, size, portMAX_DELAY);
}
